package com.atguigu.aiproject.service.impl;

import com.atguigu.aiproject.mapper.CreationMapper;
import com.atguigu.aiproject.service.CreationViewService;
import com.atguigu.aiproject.utils.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;

import static com.atguigu.aiproject.constant.RedisKeyConstant.CREATION_DETAIL_KEY;
import static com.atguigu.aiproject.constant.RedisKeyConstant.CREATION_VIEW_BITMAP_KEY;

@Service
@Slf4j
public class CreationViewServiceImpl implements CreationViewService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private CreationMapper creationMapper;
    /**
     * 增加浏览量（同一用户24小时内只能贡献一次）
     * 使用BitMap优化浏览量统计,每个作品只用一个key
     */
    @Override
    public void increaseViewCount(Integer creationId) {
        Integer currentUserId = UserContext.getUserId();
        if (currentUserId == null || currentUserId <= 0) {
            return;
        }
        String bitmapKey = CREATION_VIEW_BITMAP_KEY + creationId;
        String detailKey = CREATION_DETAIL_KEY + creationId;
        try {
            // 使用用户ID作为偏移量（需要处理用户ID过大问题）
            long offset = getSafeOffset(currentUserId);

            // 原子操作：检查并设置位
            Boolean notViewed = redisTemplate.opsForValue().setBit(bitmapKey, offset, true);

            if (Boolean.FALSE.equals(notViewed)) {
                // 之前未设置过，增加浏览量
                CompletableFuture.runAsync(() -> {
                    try {
                        creationMapper.incrementClickCount(creationId);
                    } catch (Exception e) {
                        log.error("更新数据库浏览量失败", e);
                        // 记录补偿日志
//                        compensationLogService.recordCompensation(creationId, currentUserId, "VIEW_ADD");
                    }
                });

                // 更新Redis中的浏览量
                redisTemplate.opsForHash().increment(detailKey, "click", 1);

                // 设置BitMap过期时间（24小时）
                redisTemplate.expire(bitmapKey, Duration.ofHours(24));
            }
        } catch (Exception e) {
            log.error("增加浏览量失败: creationId={}, userId={}", creationId, currentUserId, e);
        }
    }

    /**
     * 将用户ID转换为安全的偏移量
     * 可以根据用户量多少来选择合适的偏移量范围
     */
    private long getSafeOffset(Integer userId) {
        //小用户量
        return Math.abs(userId.longValue()) % 1_000_00;
        //大用户量
//        int hash = Objects.hash(userId, "view_salt"); // 加盐避免规律性
//        long unsignedHash = Integer.toUnsignedLong(hash);
//        return Math.abs(unsignedHash) % 2_000_000; // 扩大范围到200万
    }
}
